package com.pubinfo.passbook.common.service.master.impl;

import cn.hutool.core.date.DateUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.metadata.WriteTable;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.pubinfo.passbook.common.entity.TContractBase;
import com.pubinfo.passbook.common.entity.TContractInvoiceHeader;
import com.pubinfo.passbook.common.entity.TContractPerformance;
import com.pubinfo.passbook.common.mapper.TContractBaseMapper;
import com.pubinfo.passbook.common.mapper.TContractInvoiceHeaderMapper;
import com.pubinfo.passbook.common.mapper.TContractPerformanceMapper;
import com.pubinfo.passbook.common.model.dto.contract.ChangeParam;
import com.pubinfo.passbook.common.model.dto.contract.ChangeUnitParam;
import com.pubinfo.passbook.common.model.dto.contract.SelectChangeUnitParam;
import com.pubinfo.passbook.common.service.master.ITFileChangeUnitService;
import com.pubinfo.passbook.common.utils.HeadStyleWriteHandler;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;

/**
 * @ClassName ITFileChangeUnitServiceImpl
 * @Author hty
 * @Date 2022/6/20 14:45
 * @Version 1.0
 **/
@Service
public class TFileChangeUnitServiceImpl extends ServiceImpl<TContractBaseMapper, TContractBase> implements ITFileChangeUnitService {
    @Autowired
    private TContractPerformanceMapper tContractPerformanceMapper;

    @Autowired
    private TContractInvoiceHeaderMapper tContractInvoiceHeaderMapper;

    @Override
    public void changeUnitDownload(HttpServletResponse response, ChangeUnitParam changeUnitParam) throws IOException, ParseException {
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        String fileName = URLEncoder.encode("单位迁改资金催收报表", "UTF-8");
        response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
        //建议加上该段，否则可能会出现前端无法获取Content-disposition
        response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
        response.setHeader("Content-Disposition", "attachment;filename*=utf-8'zh_cn'" + fileName + ".xlsx");
        // 创建一个表格，用于 Sheet 中使用
        WriteTable table = new WriteTable();
        table.setTableNo(1);
        table.setHead(head(changeUnitParam));
        List<List<String>> head = table.getHead();
        List<List<Object>> list = contentData(changeUnitParam);
        //自定义样式
        int columnIndexes = head.size() - 1;
        HeadStyleWriteHandler customCellStyleStrategy = new HeadStyleWriteHandler(columnIndexes);
        // 写数据
        EasyExcel.write(response.getOutputStream())
                .head(head)
                .registerWriteHandler(customCellStyleStrategy)
                .sheet("单位迁改资金催收报表")
                .doWrite(firstDetail(list));
    }


    /**
     * 动态生成表头
     *
     * @param changeUnitParam
     * @return
     */
    private List<List<String>> head(ChangeUnitParam changeUnitParam) {
        List<List<String>> headTitles = Lists.newArrayList();
        String basicInfo = "单位迁改资金催收报表";
        String collectionMessage = "合同履约收款信息";
        String alreadyCollection = "已收款";
        List<String> skuTitles = Lists.newArrayList("单位", "合同编号", "合同名称", "合同迁改单位", "认领员", "合同性质", "合同金额", "最终收款");
        skuTitles.forEach(title -> {
            headTitles.add(Lists.newArrayList(basicInfo, title));
        });

        List<Integer> monthList = Lists.newArrayList();
        List<TContractBase> baseList = this.baseMapper.selectChangeUint(changeUnitParam);
        if (!baseList.isEmpty()) {
            for (int i = 0; i < baseList.size(); i++) {
                QueryWrapper<TContractPerformance> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("contract_id", baseList.get(i).getContractId());
                List performanceList = tContractPerformanceMapper.selectList(queryWrapper).stream()
                        .map(TContractPerformance::getTimeNo).collect(Collectors.toList());
                for (Object num : performanceList) {
                    monthList.add(Integer.valueOf(num.toString()));
                }
            }

            //动态生成收款表头
            List<String> orderSpeaces = Lists.newArrayList("金额", "收款时间");
            monthList.forEach(collection -> {
                orderSpeaces.forEach(title -> {
                    headTitles.add(Lists.newArrayList(basicInfo, collectionMessage, "第" + collection + "次收款", title));
                });
            });
        } else {
            //默认只生成一次收款
            List<Integer> monthListOne = Lists.newArrayList(1);
            List<String> orderSpeaces = Lists.newArrayList("金额", "收款时间");
            monthListOne.forEach(collection -> {
                orderSpeaces.forEach(title -> {
                    headTitles.add(Lists.newArrayList(basicInfo, collectionMessage, "第1次收款", title));
                });
            });
        }


        List<String> collection = Lists.newArrayList("累计收款金额", "最后一次收款金额", "累计开票金额", "最后一次开票时间");
        collection.forEach(title -> {
            headTitles.add(Lists.newArrayList(basicInfo, alreadyCollection, title));
        });

        List<String> lastList = Lists.newArrayList("应催收金额");
        lastList.forEach(title -> {
            headTitles.add(Lists.newArrayList(basicInfo, title));
        });

        return headTitles;
    }

    /**
     * 添加列表数据
     *
     * @param changeUnitParam
     * @return
     * @throws ParseException
     */
    private List<List<Object>> contentData(ChangeUnitParam changeUnitParam) throws ParseException {
        List<List<Object>> contentList = Lists.newArrayList();
        List<TContractBase> baseList = this.baseMapper.selectChangeUint(changeUnitParam);
        if (baseList.isEmpty()) {
            return contentList;
        }
        int max = 0;
        for (TContractBase tContractBase : baseList) {
            QueryWrapper<TContractPerformance> query = new QueryWrapper<>();
            query.eq("contract_id", tContractBase.getContractId());
            List<TContractPerformance> perforList = tContractPerformanceMapper.selectList(query);
            int size = perforList.stream().map(r -> r.getTimeNo()).collect(Collectors.toList()).size();
            if (size > max) {
                max = size;
            }
        }
        for (TContractBase tContractBase : baseList) {
            List<Object> list = new ArrayList<>();
            list.add(tContractBase.getCompany());
            list.add(tContractBase.getContractCode());
            list.add(tContractBase.getContractName());
            list.add(tContractBase.getPartbName());
            list.add(tContractBase.getProcessUser());
    
            list.add(tContractBase.getAccountCase());
            list.add(tContractBase.getContractAmount().toString());
            list.add(tContractBase.getContractAmount().toString());
            //获取合同履约收款信息
            QueryWrapper<TContractPerformance> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("contract_id", tContractBase.getContractId());
            List<TContractPerformance> performanceList = tContractPerformanceMapper.selectList(queryWrapper);
            if (!performanceList.isEmpty()) {
                int size = performanceList.stream().map(r -> r.getTimeNo()).collect(Collectors.toList()).size();
                //计算收款金额
                BigDecimal bigDecimal = new BigDecimal("0");
                DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX", Locale.US);
                for (TContractPerformance performance : performanceList) {
                    BigDecimal amounts = new BigDecimal(performance.getCollectAmount());
                  list.add(performance.getCollectAmount());
                  list.add(DateUtil.format(performance.getPayDate(), "yyyy-MM-dd HH:mm:ss"));
                  bigDecimal = bigDecimal.add(amounts);
                }
                //判断是否为最大收款数，若不是，则将后面单元格置空
                if (max > size) {
                    int num = max - size;
                    for (int j = 0; j < num; j++) {
                        list.add(null);
                        list.add(null);
                    }
                }
                list.add(bigDecimal.toString());
                List<String> collect = performanceList.stream().map(TContractPerformance::getCollectAmount).collect(Collectors.toList());
                list.add(collect.get(collect.size() - 1));
            } else {
                list.add(null);
                list.add(null);
            }

            //获取已收款信息
            QueryWrapper<TContractInvoiceHeader> query = new QueryWrapper<>();
            query.eq("contract_id", tContractBase.getContractId());
            List<TContractInvoiceHeader> headerList = tContractInvoiceHeaderMapper.selectList(query);
            if (!headerList.isEmpty()) {
                BigDecimal headerDecimal = new BigDecimal("0");
                for (TContractInvoiceHeader header : headerList) {
                    headerDecimal = headerDecimal.add(header.getInvoiceAmount());
                }
                list.add(headerDecimal.toString());
                List<Date> headercollect = headerList.stream().map(TContractInvoiceHeader::getCreateTime).collect(Collectors.toList());
                list.add(headercollect.get(headercollect.size() - 1));
            } else {
                list.add(0);
                list.add(null);
            }
            //应催收金额
            list.add("11");
            contentList.add(list);
        }
        return contentList;
    }

    private List<List<Object>> firstDetail(List<List<Object>> mapList) {
        List<List<Object>> list = new ArrayList<List<Object>>();
        for (List<Object> map : mapList) {
            List<Object> objectList = new ArrayList<>();
            for (int i = 0; i < map.size(); i++) {
                objectList.add(map.get(i));
            }
            list.add(objectList);
        }
        return list;
    }


    @Override
    public IPage<SelectChangeUnitParam> selectStatement(ChangeUnitParam changeUnitParam) throws ParseException {
        IPage<SelectChangeUnitParam> IPage = changeUnitParam.getMyPage();
        List<SelectChangeUnitParam> list = new ArrayList<>();
        SelectChangeUnitParam param = new SelectChangeUnitParam();
        List<TContractBase> baseList = this.baseMapper.selectChangeUintList(IPage,changeUnitParam);
        for (int i = 0; i < baseList.size(); i++) {
            BeanUtils.copyProperties(baseList.get(i), param);
            QueryWrapper<TContractPerformance> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("contract_id", baseList.get(i).getContractId());
            List<TContractPerformance> performanceList = tContractPerformanceMapper.selectList(queryWrapper);
            List<ChangeParam> performancelist = new ArrayList<>();
            BigDecimal bigDecimal = new BigDecimal("0");
            for (TContractPerformance performance : performanceList) {
              ChangeParam changeParam = new ChangeParam();
              BigDecimal amounts = new BigDecimal(performance.getCollectAmount());
              changeParam.setPrice(performance.getCollectAmount());
  
              changeParam.setDatetime(DateUtil.format(performance.getPayDate(), "yyyy-MM-dd HH:mm:ss"));
              performancelist.add(changeParam);
              param.setCollectList(performancelist);
              bigDecimal = bigDecimal.add(amounts);
            }
            param.setCumulativPrice(bigDecimal.toString());
            List<String> collect = performanceList.stream().map(TContractPerformance::getCollectAmount).collect(Collectors.toList());
            param.setEndPriceTime(collect.get(collect.size() - 1));
            QueryWrapper<TContractInvoiceHeader> query = new QueryWrapper<>();
            query.eq("contract_id", baseList.get(i).getContractId());
            List<TContractInvoiceHeader> headerList = tContractInvoiceHeaderMapper.selectList(query);
            if (!headerList.isEmpty()) {
                BigDecimal headerDecimal = new BigDecimal("0");
                for (TContractInvoiceHeader header : headerList) {
                    headerDecimal = headerDecimal.add(header.getInvoiceAmount());
                }
                param.setCumulativeMoney(headerDecimal.toString());
                List<Date> headercollect = headerList.stream().map(TContractInvoiceHeader::getCreateTime).collect(Collectors.toList());
                param.setEndDateTime(headercollect.get(headercollect.size() - 1).toString());
            }
            list.add(param);
        }
        IPage.setRecords(list);
        return IPage;
    }

}
